/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <flgrCoreDataIO.h>
#include <flgrCoreDispatch.h>
#include "flgrImageColorSpace.h"



/****************************************** 1D ********************************************/


/*!
 * \defgroup group_fulguro_image_color_space_transform Color Space Transform and Channel Extraction
 * \ingroup group_fulguro_image
 * Functions to convert color space and to extract color channel
 * @{
 */






/*     (R, V, B, Y) -> [0 ; 1] */
/*     U -> [-0,436 ; 0,436] */
/*     V -> [-0,615 ; 0,615]  */


#define FLGR_MACRO_CONVERT1D_YUV_RGB_UNSIGNED(dtype,fdtype)	\
  dtype *pdest = datdest->array;				\
  dtype *psrc = datsrc->array;					\
  fdtype tR,tG,tB,tmp;						\
  int i;							\
								\
  for(i=0 ; i<datdest->length*3 ; i+=3) {			\
    tR = (fdtype) flgr1d_get_data_array_##dtype(psrc,i);	\
    tG = (fdtype) flgr1d_get_data_array_##dtype(psrc,i+1);	\
    tB = (fdtype) flgr1d_get_data_array_##dtype(psrc,i+2);	\
								\
    tmp = 0.299*tR + 0.597*tG + 0.114*tB;			\
    tmp = (tmp>MAX_##dtype) ? MAX_##dtype : tmp;		\
    tmp = (tmp<MIN_##dtype) ? MIN_##dtype : tmp;		\
    flgr1d_set_data_array_##dtype(pdest,i,(dtype) tmp);		\
								\
    tmp = -0.14713*tR - 0.28886*tG + 0.436*tB;			\
    tmp += 0.436*MAX_##dtype;					\
    tmp /= (0.436*2);						\
    tmp = (tmp>MAX_##dtype) ? MAX_##dtype : tmp;		\
    tmp = (tmp<MIN_##dtype) ? MIN_##dtype : tmp;		\
    flgr1d_set_data_array_##dtype(pdest,i+1,(dtype) tmp);	\
								\
    tmp = 0.615*tR - 0.51499*tG - 0.10001*tB;			\
    tmp += 0.615*MAX_##dtype;					\
    tmp /= (0.615*2);						\
    tmp = (tmp>MAX_##dtype) ? MAX_##dtype : tmp;		\
    tmp = (tmp<MIN_##dtype) ? MIN_##dtype : tmp;		\
    flgr1d_set_data_array_##dtype(pdest,i+2,(dtype) tmp);	\
								\
  }								\
  return 

#define FLGR_MACRO_CONVERT1D_YUV_RGB_SIGNED(dtype,fdtype)	\
  dtype *pdest = datdest->array;				\
  dtype *psrc = datsrc->array;					\
  fdtype tR,tG,tB,tmp;						\
  int i;							\
								\
  for(i=0 ; i<datdest->length*3 ; i+=3) {			\
    tR = (fdtype) flgr1d_get_data_array_##dtype(psrc,i);	\
    tG = (fdtype) flgr1d_get_data_array_##dtype(psrc,i+1);	\
    tB = (fdtype) flgr1d_get_data_array_##dtype(psrc,i+2);	\
								\
    tmp = 0.299*tR + 0.597*tG + 0.114*tB;			\
    tmp = (tmp>MAX_##dtype) ? MAX_##dtype : tmp;		\
    tmp = (tmp<MIN_##dtype) ? MIN_##dtype : tmp;		\
    flgr1d_set_data_array_##dtype(pdest,i,(dtype) tmp);		\
								\
    tmp = -0.14713*tR - 0.28886*tG + 0.436*tB;			\
    tmp /= (0.436*2);						\
    tmp = (tmp>MAX_##dtype) ? MAX_##dtype : tmp;		\
    tmp = (tmp<MIN_##dtype) ? MIN_##dtype : tmp;		\
    flgr1d_set_data_array_##dtype(pdest,i+1,(dtype) tmp);	\
								\
    tmp = 0.615*tR - 0.51499*tG - 0.10001*tB;			\
    tmp /= (0.615*2);						\
    tmp = (tmp>MAX_##dtype) ? MAX_##dtype : tmp;		\
    tmp = (tmp<MIN_##dtype) ? MIN_##dtype : tmp;		\
    flgr1d_set_data_array_##dtype(pdest,i+2,(dtype) tmp);	\
								\
  }								\
  return 

#define FLGR_MACRO_CONVERT1D_YUV_RGB_FLOAT(dtype,fdtype)	\
  dtype *pdest = datdest->array;				\
  dtype *psrc = datsrc->array;					\
  fdtype tR,tG,tB,tmp;						\
  int i;							\
								\
  for(i=0 ; i<datdest->length*3 ; i+=3) {			\
    tR = (fdtype) flgr1d_get_data_array_##dtype(psrc,i);	\
    tG = (fdtype) flgr1d_get_data_array_##dtype(psrc,i+1);	\
    tB = (fdtype) flgr1d_get_data_array_##dtype(psrc,i+2);	\
								\
    tmp = 0.299*tR + 0.597*tG + 0.114*tB;			\
    flgr1d_set_data_array_##dtype(pdest,i,(dtype) tmp);		\
								\
    tmp = -0.14713*tR - 0.28886*tG + 0.436*tB;			\
    flgr1d_set_data_array_##dtype(pdest,i+1,(dtype) tmp);	\
								\
    tmp = 0.615*tR - 0.51499*tG - 0.10001*tB;			\
    flgr1d_set_data_array_##dtype(pdest,i+2,(dtype) tmp);	\
								\
  }								\
  return 


void flgr1d_color_convert_YUV_RGB_fgBIT(FLGR_Data1D *datdest, FLGR_Data1D *datsrc) {
  flgr_no_define_type_function(FLGR_BIT);  
}

void flgr1d_color_convert_YUV_RGB_fgUINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc) {
  fgUINT8 *pdest = datdest->array;
  fgUINT8 *psrc = datsrc->array;
  fgINT16 tR,tG,tB,tmp;
  int i;

  for(i=0 ; i<datdest->length*3 ; i+=3) {
    tR = (fgINT16) flgr1d_get_data_array_fgUINT8(psrc,i);
    tG = (fgINT16) flgr1d_get_data_array_fgUINT8(psrc,i+1);
    tB = (fgINT16) flgr1d_get_data_array_fgUINT8(psrc,i+2);

    tmp = ((66*tR + 129*tG + 25*tB + 128) >> 8) + 16;
    flgr1d_set_data_array_fgUINT8(pdest,i,(fgUINT8) tmp);

    tmp = ((-38*tR -  74*tG + 112*tB + 128) >> 8) + 128;
    flgr1d_set_data_array_fgUINT8(pdest,i+1,(fgUINT8) tmp);
    
    tmp = ((112*tR -  94*tG -  18*tB + 128) >> 8) + 128;
    flgr1d_set_data_array_fgUINT8(pdest,i+2,(fgUINT8) tmp);

  }
}

void flgr1d_color_convert_YUV_RGB_fgUINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_YUV_RGB_UNSIGNED(fgUINT16,fgFLOAT32);
}

void flgr1d_color_convert_YUV_RGB_fgUINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_YUV_RGB_UNSIGNED(fgUINT32,fgFLOAT32); 
}

void flgr1d_color_convert_YUV_RGB_fgINT8(FLGR_Data1D *datdest, FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_YUV_RGB_SIGNED(fgINT8,fgFLOAT32); 
}

void flgr1d_color_convert_YUV_RGB_fgINT16(FLGR_Data1D *datdest, FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_YUV_RGB_SIGNED(fgINT16,fgFLOAT32);  
}

void flgr1d_color_convert_YUV_RGB_fgINT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_YUV_RGB_SIGNED(fgINT32,fgFLOAT32); 
}

void flgr1d_color_convert_YUV_RGB_fgFLOAT32(FLGR_Data1D *datdest, FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_YUV_RGB_FLOAT(fgFLOAT32,fgFLOAT32); 
}

void flgr1d_color_convert_YUV_RGB_fgFLOAT64(FLGR_Data1D *datdest, FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_YUV_RGB_FLOAT(fgFLOAT64,fgFLOAT64); 
}

//////////////////////////////////////////////////////////////////
/*! Convert RGB channels to YUV channels
 *
 *  RGB sample must be stored in memory  : R0 G0 B0 R1 G2 B2 R3 G3 ...
 *  YUV sample will be stored in memory  : Y0 U0 V0 Y1 U2 V2 Y3 U3 ...
 *
 *  Conversion matrix used for unsigned 8 bits :
 *    \f[Y = (( 66 \cdot R +  129 \cdot G +  25 \cdot B + 128) / 256) + 16\f]
 *    \f[U = ((-38 \cdot R -   74 \cdot G + 112 \cdot B + 128) / 256) + 128\f]
 *    \f[V = ((112 \cdot R -   94 \cdot G -  18 \cdot B + 128) / 256) + 128\f]
 *
 *  Conversion matrix used for all others types :
 *   \f[Y = 0.2990 \cdot R + 0.587 \cdot G + 0.114 \cdot B\f]
 *   \f[U = -0.147 \cdot R - 0.289 \cdot G + 0.436 \cdot B\f]
 *   \f[V = 0.6150 \cdot R - 0.515 \cdot G - 0.100 \cdot B\f]
 *
 *  - FLGR_UINT8 :
 *  	 - internal FGLR_UINT16 conversion performed
 *  	 - R,G,B,Y in [0 ; 2^8-1] 
 *  	 - U in [0 ; 2^8-1]
 *  	 - V in [0 ; 2^8-1]
 *
 *  - FLGR_UINT16 :
 *  	 - internal float conversion performed
 *  	 - R,G,B,Y in [0 ; 2^16-1] 
 *  	 - U in [0 ; 2^16-1]
 *  	 - V in [0 ; 2^16-1]
 *
 *  - FLGR_UINT32 :
 *  	 - internal float conversion performed
 *  	 - R,G,B,Y in [0 ; 2^32-1] 
 *  	 - U in [0 ; 2^32-1]
 *  	 - V in [0 ; 2^32-1]
 *
 *  - FLGR_INT8 :
 *  	 - internal float conversion performed
 *  	 - R,G,B,Y in [-2^7 ; 2^7-1] 
 *  	 - U in [-2^7 ; 2^7-1]
 *  	 - V in [-2^7 ; 2^7-1]
 *
 *  - FLGR_INT16 :
 *  	 - internal float conversion performed
 *  	 - R,G,B,Y in [-2^15 ; 2^15-1] 
 *  	 - U in [-2^15 ; 2^15-1]
 *  	 - V in [-2^15 ; 2^15-1]
 *
 *  - FLGR_INT32 :
 *       - internal float conversion performed
 *       - R,G,B,Y in [-2^31 ; 2^31-1] 
 *       - U in [-2^31 ; 2^31-1]
 *  	 - V in [-2^31 ; 2^31-1]
 *
 *  - FLGR_FLOAT32 and FLGR_FLOAT64 :
 *  	 - R,G,B,Y in [0 ; 1] 
 *  	 - U in [-0.436 ; 0.436]
 *  	 - V in [-0.615 ; 0.615]
 *
 *  @param datdest : destination YUV image (spp=3)
 *  @param datsrc  : source RGB image (spp=3)
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_color_convert_YUV_RGB(FLGR_Data1D *datdest, FLGR_Data1D *datsrc) {
  FLGR_Ret ret;

  if((datdest==NULL) || (datsrc==NULL)) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret = flgr1d_is_data_same_attributes(datdest,datsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  if(datdest->spp != 3) {
    POST_ERROR("Bad sample per pixel in source or destination\n");
    return FLGR_RET_PARAM_ERROR;
  }

  FLGR_DISPATCH_PROCEDURE(datsrc->type,flgr1d_color_convert_YUV_RGB,datdest,datsrc);
  
}





#define FLGR_MACRO_CONVERT1D_RGB_YUV_UNSIGNED(dtype,fdtype)	\
  dtype *psrc = datsrc->array;					\
  dtype *pdest = datdest->array;				\
								\
  fdtype tY,tU,tV,tD,tE,tmp;					\
								\
  int i;							\
								\
  for(i=0 ; i<datdest->length*3 ; i+=3) {			\
    tY = (fdtype) flgr1d_get_data_array_##dtype(psrc,i);	\
    tU = (fdtype) flgr1d_get_data_array_##dtype(psrc,i+1);	\
    tV = (fdtype) flgr1d_get_data_array_##dtype(psrc,i+2);	\
    tD = tU*(0.436*2) - 0.436*MAX_##dtype;			\
    tE = tV*(0.615*2) - 0.615*MAX_##dtype;			\
								\
    tmp = tY - 0.00004*tD + 1.13983*tE;				\
    tmp = (tmp>MAX_##dtype) ? MAX_##dtype : tmp;		\
    tmp = (tmp<MIN_##dtype) ? MIN_##dtype : tmp;		\
    flgr1d_set_data_array_##dtype(pdest,i,(dtype) tmp);		\
								\
    tmp = tY - 0.39465*tD - 0.58060*tE;				\
    tmp = (tmp>MAX_##dtype) ? MAX_##dtype : tmp;		\
    tmp = (tmp<MIN_##dtype) ? MIN_##dtype : tmp;		\
    flgr1d_set_data_array_##dtype(pdest,i+1,(dtype) tmp);	\
								\
    tmp = tY + 2.03211*tD - 0.0005*tE;				\
    tmp = (tmp>MAX_##dtype) ? MAX_##dtype : tmp;		\
    tmp = (tmp<MIN_##dtype) ? MIN_##dtype : tmp;		\
    flgr1d_set_data_array_##dtype(pdest,i+2,(dtype) tmp);	\
								\
  }								\
  return 

#define FLGR_MACRO_CONVERT1D_RGB_YUV_SIGNED(dtype,fdtype)	\
  dtype *psrc = datsrc->array;					\
  dtype *pdest = datdest->array;				\
								\
  fdtype tY,tU,tV,tD,tE,tmp;					\
								\
  int i;							\
								\
  for(i=0 ; i<datdest->length*3 ; i+=3) {			\
    tY = (fdtype) flgr1d_get_data_array_##dtype(psrc,i);	\
    tU = (fdtype) flgr1d_get_data_array_##dtype(psrc,i+1);	\
    tV = (fdtype) flgr1d_get_data_array_##dtype(psrc,i+2);	\
    tD = tU*0.436*2;						\
    tE = tV*0.615*2;						\
								\
    tmp = tY + 1.13983*tE;					\
    tmp = (tmp>MAX_##dtype) ? MAX_##dtype : tmp;		\
    tmp = (tmp<MIN_##dtype) ? MIN_##dtype : tmp;		\
    flgr1d_set_data_array_##dtype(pdest,i,(dtype) tmp);		\
								\
    tmp = tY - 0.39465*tD - 0.58060*tE;				\
    tmp = (tmp>MAX_##dtype) ? MAX_##dtype : tmp;		\
    tmp = (tmp<MIN_##dtype) ? MIN_##dtype : tmp;		\
    flgr1d_set_data_array_##dtype(pdest,i+1,(dtype) tmp);	\
								\
    tmp = tY + 2.03211*tD;					\
    tmp = (tmp>MAX_##dtype) ? MAX_##dtype : tmp;		\
    tmp = (tmp<MIN_##dtype) ? MIN_##dtype : tmp;		\
    flgr1d_set_data_array_##dtype(pdest,i+2,(dtype) tmp);	\
								\
  }								\
  return 

#define FLGR_MACRO_CONVERT1D_RGB_YUV_FLOAT(dtype,fdtype)	\
  dtype *psrc = datsrc->array;					\
  dtype *pdest = datdest->array;				\
								\
  fdtype tY,tU,tV,tD,tE,tmp;					\
								\
  int i;							\
								\
  for(i=0 ; i<datdest->length*3 ; i+=3) {			\
    tY = (fdtype) flgr1d_get_data_array_##dtype(psrc,i);	\
    tU = (fdtype) flgr1d_get_data_array_##dtype(psrc,i+1);	\
    tV = (fdtype) flgr1d_get_data_array_##dtype(psrc,i+2);	\
    tD = tU;							\
    tE = tV;							\
								\
    tmp = tY + 1.13983*tE;					\
    flgr1d_set_data_array_##dtype(pdest,i,(dtype) tmp);		\
								\
    tmp = tY - 0.39465*tD - 0.58060*tE;				\
    flgr1d_set_data_array_##dtype(pdest,i+1,(dtype) tmp);	\
								\
    tmp = tY + 2.03211*tD;					\
    flgr1d_set_data_array_##dtype(pdest,i+2,(dtype) tmp);	\
								\
  }								\
  return 

void flgr1d_color_convert_RGB_YUV_fgBIT(FLGR_Data1D *datdest,FLGR_Data1D *datsrc) {
  flgr_no_define_type_function(FLGR_BIT);  
}

void flgr1d_color_convert_RGB_YUV_fgUINT8(FLGR_Data1D *datdest,FLGR_Data1D *datsrc) {
  fgUINT8 *psrc = datsrc->array;
  fgUINT8 *pdest = datdest->array;

  fgINT16 tY,tU,tV,tmp,tC,tD,tE;

  int i;

  for(i=0 ; i<datdest->length*3 ; i+=3) {
    tY = (fgINT16) flgr1d_get_data_array_fgUINT8(psrc,i);
    tU = (fgINT16) flgr1d_get_data_array_fgUINT8(psrc,i+1);
    tV = (fgINT16) flgr1d_get_data_array_fgUINT8(psrc,i+2);
    tC = tY - 16;
    tD = tU - 128;
    tE = tV - 128;

    tmp = ( 298 * tC + 409 * tE + 128) >> 8;
    tmp = (tmp>MAX_fgUINT8) ? MAX_fgUINT8 : tmp;
    tmp = (tmp<MIN_fgUINT8) ? MIN_fgUINT8 : tmp;
    flgr1d_set_data_array_fgUINT8(pdest,i,(fgUINT8) tmp);

    tmp = ( 298 * tC - 100 * tD - 208 * tE + 128) >> 8;
    tmp = (tmp>MAX_fgUINT8) ? MAX_fgUINT8 : tmp;
    tmp = (tmp<MIN_fgUINT8) ? MIN_fgUINT8 : tmp;
    flgr1d_set_data_array_fgUINT8(pdest,i+1,(fgUINT8) tmp);
    
    tmp = ( 298 * tC + 516 * tD + 128) >> 8;
    tmp = (tmp>MAX_fgUINT8) ? MAX_fgUINT8 : tmp;
    tmp = (tmp<MIN_fgUINT8) ? MIN_fgUINT8 : tmp;
    flgr1d_set_data_array_fgUINT8(pdest,i+2,(fgUINT8) tmp);

  }
  //FLGR_MACRO_CONVERT1D_RGB_YUV_UNSIGNED(fgUINT8,fgFLOAT32); 
}

void flgr1d_color_convert_RGB_YUV_fgUINT16(FLGR_Data1D *datdest,FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_RGB_YUV_UNSIGNED(fgUINT16,fgFLOAT32); 
}

void flgr1d_color_convert_RGB_YUV_fgUINT32(FLGR_Data1D *datdest,FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_RGB_YUV_UNSIGNED(fgUINT32,fgFLOAT32);
}

void flgr1d_color_convert_RGB_YUV_fgINT8(FLGR_Data1D *datdest,FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_RGB_YUV_SIGNED(fgINT8,fgFLOAT32); 
}

void flgr1d_color_convert_RGB_YUV_fgINT16(FLGR_Data1D *datdest,FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_RGB_YUV_SIGNED(fgINT16,fgFLOAT32);  
}

void flgr1d_color_convert_RGB_YUV_fgINT32(FLGR_Data1D *datdest,FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_RGB_YUV_SIGNED(fgINT32,fgFLOAT32); 
}

void flgr1d_color_convert_RGB_YUV_fgFLOAT32(FLGR_Data1D *datdest,FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_RGB_YUV_FLOAT(fgFLOAT32,fgFLOAT32); 
}

void flgr1d_color_convert_RGB_YUV_fgFLOAT64(FLGR_Data1D *datdest,FLGR_Data1D *datsrc) {
  FLGR_MACRO_CONVERT1D_RGB_YUV_FLOAT(fgFLOAT64,fgFLOAT64); 
}

//////////////////////////////////////////////////////////////////
/*! Convert YUV channels to RGB channels
 *
 *  RGB sample must be stored in memory  : R0 G0 B0 R1 G2 B2 R3 G3 ...
 *  YUV sample will be stored in memory  : Y0 U0 V0 Y1 U2 V2 Y3 U3 ...
 *
 *  Conversion matrix used for unsigned 8 bits :
 *  \f[R = ( 298 \cdot (Y-16) + 409 \cdot (V-128) + 128) / 256\f]
 *  \f[G = ( 298 \cdot (Y-16) - 100 \cdot (U-128) - 208 \cdot (V-128) + 128) / 256 \f]
 *  \f[B = ( 298 \cdot (Y-16) + 516 \cdot (U-128) + 128) / 256\f]
 *
 *  Conversion matrix used for all others types :
 *  \f[R = 1 \cdot Y - 0.00004 \cdot U + 1.1400 \cdot V\f]
 *  \f[G = 1 \cdot Y - 0.39500 \cdot U - 0.5810 \cdot V\f]
 *  \f[B = 1 \cdot Y + 2.03200 \cdot U - 0.0005 \cdot V\f]
 *
 *  - FLGR_UINT8 :
 *  	 - No internal float conversion performed
 *  	 - R,G,B,Y in [0 ; 2^8-1] 
 *  	 - U in [0 ; 2^8-1]
 *  	 - V in [0 ; 2^8-1]
 *
 *  - FLGR_UINT16 :
 *  	 - internal float conversion performed
 *  	 - R,G,B,Y in [0 ; 2^16-1] 
 *  	 - U in [0 ; 2^16-1]
 *  	 - V in [0 ; 2^16-1]
 *
 *  - FLGR_UINT32 :
 *  	 - internal float conversion performed
 *  	 - R,G,B,Y in [0 ; 2^32-1] 
 *  	 - U in [0 ; 2^32-1]
 *  	 - V in [0 ; 2^32-1]
 *
 *  - FLGR_INT8 :
 *  	 - internal float conversion performed
 *  	 - R,G,B,Y in [-2^7 ; 2^7-1] 
 *  	 - U in [-2^7 ; 2^7-1]
 *  	 - V in [-2^7 ; 2^7-1]
 *
 *  - FLGR_INT16 :
 *  	 - internal float conversion performed
 *  	 - R,G,B,Y in [-2^15 ; 2^15-1] 
 *  	 - U in [-2^15 ; 2^15-1]
 *  	 - V in [-2^15 ; 2^15-1]
 *
 *  - FLGR_INT32 :
 *       - internal float conversion performed
 *  	 - R,G,B,Y in [-2^31 ; 2^31-1] 
 *  	 - U in [-2^31 ; 2^31-1]
 *  	 - V in [-2^31 ; 2^31-1]
 *
 *  - FLGR_FLOAT32 and FLGR_FLOAT64 :
 *  	 - R,G,B,Y in [0 ; 1] 
 *  	 - U in [-0.436 ; 0.436]
 *  	 - V in [-0.615 ; 0.615]
 *
 *  @param datdest : pointer to a FLGR_Data1D
 *  @param datsrc : pointer to a FLGR_Data1D  
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_color_convert_RGB_YUV(FLGR_Data1D *datdest, FLGR_Data1D *datsrc) {
  FLGR_Ret ret;

  if((datsrc==NULL)  || (datdest==NULL)) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret = flgr1d_is_data_same_attributes(datsrc,datdest,__FUNCTION__)) != FLGR_RET_OK) return ret;

  if(datdest->spp != 3) {
    POST_ERROR("Bad sample per pixel in source or destination\n");
    return FLGR_RET_PARAM_ERROR;
  }

  FLGR_DISPATCH_PROCEDURE(datdest->type,flgr1d_color_convert_RGB_YUV,datdest,datsrc);
}





/************************************* 2D Functions ***************************************/



#define FLGR_MACRO_COLOR_CONVERT2D_YUV_RGB(dtype)			\
  FLGR_Data1D **dest = datdest->row;					\
  FLGR_Data1D **src = datsrc->row;					\
  int i;								\
									\
  for(i=0 ; i<datsrc->size_y ; i++) {					\
    flgr1d_color_convert_YUV_RGB_##dtype(*dest,*src);			\
    dest++;src++;							\
  }									\
  return

void flgr2d_color_convert_YUV_RGB_fgBIT(FLGR_Data2D *datdest, FLGR_Data2D *datsrc) {
  flgr_no_define_type_function(FLGR_BIT);  
}
void flgr2d_color_convert_YUV_RGB_fgUINT8(FLGR_Data2D *datdest, FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_YUV_RGB(fgUINT8);
}
void flgr2d_color_convert_YUV_RGB_fgUINT16(FLGR_Data2D *datdest, FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_YUV_RGB(fgUINT16);
}
void flgr2d_color_convert_YUV_RGB_fgUINT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_YUV_RGB(fgUINT32);
}
void flgr2d_color_convert_YUV_RGB_fgINT8(FLGR_Data2D *datdest, FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_YUV_RGB(fgINT8);
}
void flgr2d_color_convert_YUV_RGB_fgINT16(FLGR_Data2D *datdest, FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_YUV_RGB(fgINT16);
}
void flgr2d_color_convert_YUV_RGB_fgINT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_YUV_RGB(fgINT32);
}
void flgr2d_color_convert_YUV_RGB_fgFLOAT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_YUV_RGB(fgFLOAT32);
}
void flgr2d_color_convert_YUV_RGB_fgFLOAT64(FLGR_Data2D *datdest, FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_YUV_RGB(fgFLOAT64);
}

//////////////////////////////////////////////////////////////////
/*! Convert RGB channels to YUV channels
 *  @param datdest
 *  @param datsrc
 *
 *  \sa flgr1d_color_convert_YUV_RGB
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_color_convert_YUV_RGB(FLGR_Data2D *datdest, FLGR_Data2D *datsrc) {
  FLGR_Ret ret;

  if((datdest==NULL) || (datsrc==NULL)) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret = flgr2d_is_data_same_attributes(datdest,datsrc,__FUNCTION__)) != FLGR_RET_OK) return ret;

  if(datdest->spp != 3) {
    POST_ERROR("Bad sample per pixel in source or destination\n");
    return FLGR_RET_PARAM_ERROR;
  }

  FLGR_DISPATCH_PROCEDURE(datsrc->type,flgr2d_color_convert_YUV_RGB,datdest,datsrc);
  
}









#define FLGR_MACRO_COLOR_CONVERT2D_RGB_YUV(dtype)			\
  FLGR_Data1D **src = datsrc->row;					\
  FLGR_Data1D **dest = datdest->row;					\
  int i;								\
									\
  for(i=0 ; i<datdest->size_y ; i++) {					\
    flgr1d_color_convert_RGB_YUV_##dtype(*dest,*src);			\
    dest++;src++;							\
  }									\
									\
  return


void flgr2d_color_convert_RGB_YUV_fgBIT(FLGR_Data2D *datdest,FLGR_Data2D *datsrc) {
  flgr_no_define_type_function(FLGR_BIT);  
}

void flgr2d_color_convert_RGB_YUV_fgUINT8(FLGR_Data2D *datdest,FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_RGB_YUV(fgUINT8);
}

void flgr2d_color_convert_RGB_YUV_fgUINT16(FLGR_Data2D *datdest,FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_RGB_YUV(fgUINT16);
}

void flgr2d_color_convert_RGB_YUV_fgUINT32(FLGR_Data2D *datdest,FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_RGB_YUV(fgUINT32);
}

void flgr2d_color_convert_RGB_YUV_fgINT8(FLGR_Data2D *datdest,FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_RGB_YUV(fgINT8);
}

void flgr2d_color_convert_RGB_YUV_fgINT16(FLGR_Data2D *datdest,FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_RGB_YUV(fgINT16);
}

void flgr2d_color_convert_RGB_YUV_fgINT32(FLGR_Data2D *datdest,FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_RGB_YUV(fgINT32);
}

void flgr2d_color_convert_RGB_YUV_fgFLOAT32(FLGR_Data2D *datdest,FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_RGB_YUV(fgFLOAT32);
}

void flgr2d_color_convert_RGB_YUV_fgFLOAT64(FLGR_Data2D *datdest,FLGR_Data2D *datsrc) {
  FLGR_MACRO_COLOR_CONVERT2D_RGB_YUV(fgFLOAT64);
}

//////////////////////////////////////////////////////////////////
/*! Convert YUV channels to RGB channels
 *  @param datdest
 *  @param datsrc
 *
 *  \sa flgr1d_color_convert_RGB_YUV
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_color_convert_RGB_YUV(FLGR_Data2D *datdest,FLGR_Data2D *datsrc) {
  FLGR_Ret ret;

  if((datsrc==NULL)  || (datdest==NULL)) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret = flgr2d_is_data_same_attributes(datsrc,datdest,__FUNCTION__)) != FLGR_RET_OK) return ret;

  if(datdest->spp != 3) {
    POST_ERROR("Bad sample per pixel in source or destination\n");
    return FLGR_RET_PARAM_ERROR;
  }

  FLGR_DISPATCH_PROCEDURE(datdest->type,flgr2d_color_convert_RGB_YUV,datdest,datsrc);
}



//! @}
